# -*- conding:UTF-8 -*-

'''
@ Project: P7_project
@ File: user.py
@ Author: 罗婷
@ Date：2022/5/27 14:57

'''
import random
from datetime import timedelta, datetime

import redis

from flask import Blueprint, jsonify, g
from flask_restful import Api, Resource, reqparse, marshal
from sqlalchemy import and_

from werkzeug.security import generate_password_hash

from common.celery_tasks.send_sms_code import send_codes
from common.model_fields.user import user_fields, channel_fields
from common.utils.jwt_util import gengrate_token
from common.utils.login_util import login_required
from models.users import *

user_bp = Blueprint('user', __name__, url_prefix='/users')
api = Api(user_bp)


class SendSmsCode(Resource):
    """容联云发送短信验证码
    步骤: 先配置容联云 2 配置celery
    1 获取手机号 2 生成短信验证码 3容联云发送短信验证码 4返回响应
    TODO 3 使用配置的容联云函数  异步delay执行 配置celery时执行容联云配置文件
    """
    def post(self):
        parser = reqparse.RequestParser()
        parser.add_argument('mobile')
        args = parser.parse_args()
        mobile = args['mobile']
        print('手机号是====>', mobile)
        # sms_code = '%s' % random.randint(100000, 999999)
        sms_code = f'{random.randint(100000, 999999)}'
        print('生成的短信验证码是====>', sms_code)
        # 容联云发送短信验证码 delay
        ret = send_codes.delay(mobile, sms_code)
        # ret = send_sms_code(mobile, sms_code)
        if ret:
            redis_cli = redis.Redis()
            redis_cli.set(mobile, sms_code, ex=3000)
            # 取一下
            sms_code = redis_cli.get(mobile)
            print('存入的验证码(是否存入===', sms_code)
            redis_cli.close()
            return jsonify(msg='发送验证码成功', code=200)
        else:
            return jsonify(msg='发送验证码失败', code=400)





class UserRegister(Resource):
    """注册"""
    def post(self):
        parser = reqparse.RequestParser()
        parser.add_argument('username')
        parser.add_argument('password')
        parser.add_argument('nickname')
        parser.add_argument('mobile')
        parser.add_argument('comfirmpassword')
        args = parser.parse_args()
        account = args['username']    # account账号
        pwd = args['password']
        nick_name = args['nickname']   # 昵称
        mobile = args['mobile']
        config_pwd = args['comfirmpassword']     # 确认密码
        print('注册密码=====>', pwd)
        print('确认密码=====>', config_pwd)
        if len(account) > 32:
            return jsonify(msg='账号太长', code=400)
        if pwd != config_pwd:
            return jsonify(msg='两次密码不一致', code=400)

        userNum = UserModel.query.filter_by(mobile=mobile).count()
        if userNum > 0:
            return jsonify(msg='手机号已存在', code=400)

        # 写入数据库
        hash_pwd = generate_password_hash(pwd)
        try:
            user = UserModel(mobile=mobile, account=account, password=hash_pwd, uname=nick_name)
            db.session.add(user)
            db.session.commit()
            return jsonify(msg='注册成功', code=200)

        except Exception as e:
            print(f'注册失败的原因是{e}')
            return jsonify(msg='注册失败', code=500)


class UserLogin(Resource):
    """登录"""
    def post(self):
        parser = reqparse.RequestParser()
        parser.add_argument('mobile')
        parser.add_argument('sms')
        args = parser.parse_args()
        mobile = args['mobile']
        sms = args['sms']

        redis_cli = redis.Redis(db=0)
        sms_code = redis_cli.get(mobile)
        print('用户输入手机号', mobile)
        print('取出数据库验证码sms_code', sms_code)
        print('用户输入验证码sms', sms)

        if not sms_code:
            return jsonify(msg='验证码已过期', code=500)

        if sms.encode() == sms_code:
            # 登录成功 生成token
            try:
                user = UserModel.query.filter_by(mobile=mobile).first()
            except Exception as e:
                print(e)
                return jsonify(msg='手机号未注册', code=400)

            data1 = {
                'user': user.account,
                'id': user.uid
            }
            # expiry = timedelta(hours=2)
            expiry = datetime.utcnow() + timedelta(hours=2)
            token = gengrate_token(data1, expiry)

            if token:
                data2 = {
                    'token': token,
                    'user_id': user.uid,
                    'refresh_token': '',
                }
                return jsonify(msg='验证通过,恭喜登录', code=200, data=data2)
            else:
                return jsonify(msg='token生成失败', code=400)

        return jsonify(msg='验证码错误', code=400)


class UserInfo(Resource):
    """用户信息"""
    def get(self, id):
        user = UserModel.query.filter_by(uid=id).first()
        if user:
            user11 = marshal(user, user_fields)
            print('user11=============', user11)
            return user11

class UpadtePwd(Resource):
    """修改密码"""

    @login_required
    def post(self, id):
        uid = g.user_id
        if uid == id:
            parser = reqparse.RequestParser()
            parser.add_argument('password')
            args = parser.parse_args()
            pwd = args['password']
            pwd_hash = generate_password_hash(pwd)
            user = UserModel.query.filter_by(uid=uid).update({''})





class UserChannels(Resource):
    """获取用户关注的频道
        判断用户是否登录
        登陆后查找用户信息
        根据用户找频道
    """
    @login_required   #强制登录
    def get(self):
        uid = g.user_id
        if uid:
            user = UserModel.query.filter_by(uid=uid).first()
            channels = marshal(user.channels, channel_fields)
            print('获取用户关注的频道', channels)
            return channels


class CancelChannel(Resource):
    """取消频道关注
      前端传来频道id
    """

    @login_required
    def get(self, id):
        uid = g.user_id
        if uid:
            user = UserModel.query.filter_by(uid=uid).first()
            # UserChannel.query.filter(and_(UserChannel.uid == user.uid, UserChannel.cid == id)).delete()
            UserChannel.query.filter_by(uid=user.uid, cid=id).delete()
            db.session.commit()
            return jsonify(message='取消关注操作成功', code=200)





# 1. 实现修改密码
# 2. 实现我的关注
# 3. 实现我的跟帖
# 4. 实现我的收藏


# 注册
api.add_resource(UserRegister, '/register')
# 发送验证码
api.add_resource(SendSmsCode, '/sen_smscode')
# 登录login
api.add_resource(UserLogin, '/login')
# 用户信息
api.add_resource(UserInfo, '/info/<int:id>')
# 用户关注频道
api.add_resource(UserChannels, '/user_channels')
# 取消关注频道
api.add_resource(CancelChannel, '/user_channels/<int:id>')
# 修改用户信息
api.add_resource(UpadtePwd, '/user_update')
